home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
FROMUTS
/
UNIXLIB37B
/
src
/
c
/
qsort
< prev
next >
Wrap
Text File
|
1991-02-13
|
3KB
|
189 lines
#ifdef __STDC__
static char sccs_id[] = "@(#) qsort.c 2.3 "__DATE__" HJR";
#else
static char sccs_id[] = "@(#) qsort.c 2.3 26/9/90 HJR";
#endif
/* qsort.c (c) Copyright 1990 H.Rogers */
#ifdef __STDC__
#include <stddef.h>
#include <stdlib.h>
#else
#include "sys/types.h"
extern void qsort();
#endif
#include <string.h>
#define N_INSERT 8
static char *__t;
static size_t __z;
#ifdef __STDC__
static int (*__c)(const void *,const void *);
#else
static int (*__c)();
#endif
/* fast insertion sort - used for n <= N_INSERT */
#ifdef __STDC__
static void __isort(register char *b,register size_t n)
#else
static void __isort(b,n)
register char *b;
register size_t n;
#endif
{
register size_t z = __z;
#ifdef __STDC__
register int (*c)(const void *,const void *) = __c;
#else
register int (*c)() = __c;
#endif
register char *m,*e,*p;
register char *t;
#define swap(x,y) (memcpy(t,x,z),memcpy(x,y,z),memcpy(y,t,z))
#define move(x,y,z) memmove(x,y,z)
#define push(x) memcpy(t,x,z)
#define pull(x) memcpy(x,t,z)
t = __t;
e = b + (n * z); /* past end */
/* find minimum */
for (m = p = b; (p += z) < e; )
if ((*c)(m,p) > 0)
m = p;
/* swap minimum into base */
if (m != b) swap(m,b);
/* standard insertion sort */
for (m = b; (p = m += z) < e; )
{
while ((*c)(p -= z,m) > 0);
if ((p += z) != m)
push(m),move(p + z,p,m - p),pull(p);
}
#undef swap
#undef move
#undef push
#undef pull
}
/* quicksort - used for n > N_INSERT */
#ifdef __STDC__
static void __qsort(register char *b,register size_t n)
#else
static void __qsort(b,n)
register char *b;
register size_t n;
#endif
{
register size_t z = __z;
#ifdef __STDC__
register int (*c)(const void *,const void *) = __c;
#else
register int (*c)() = __c;
#endif
register char *m,*e,*p,*t;
register int i,j,k;
#define swap(x,y) (memcpy(t,x,z),memcpy(x,y,z),memcpy(y,t,z))
loop:
t = __t;
m = b + ((n>>1) * z); /* middle */
e = b + ((n - 1) * z); /* end */
/* find pivot - median of b,m,e */
if ((*c)(b,m) >= 0) p = b; else p = m,m = b;
if ((*c)(p,e) > 0) p = ((*c)(m,e) >= 0) ? m : e;
/* swap pivot into base */
if (p != b) swap(p,b);
/* standard quicksort & check for flat partition */
m = b; i = 0; j = 1;
for (p = b; (p += z) <= e; )
{
if (!(k = (*c)(p,b))) j++;
if (k < 0)
{ if ((m += z) != p) swap(m,p); i++; }
}
if (j == n) return; /* exit if flat */
if (b != m) swap(b,m);
m += z;
/* sort smallest partition first */
if (i < (n>>1))
{
if (i > N_INSERT)
__qsort(b,i);
else if (i > 1)
__isort(b,i);
i = n - i - 1;
}
else
{
i = n - i - 1;
if (i > N_INSERT)
__qsort(m,i);
else if (i > 1)
__isort(m,i);
i = n - i - 1;
m = b;
}
if (i > N_INSERT)
{ b = m; n = i; goto loop; } /* iterate larger partition */
else if (i > 1)
__isort(m,i);
#undef swap
}
#ifdef __STDC__
void qsort(register void *v,register size_t n,register size_t z,
register int (*c)(const void *,const void *))
#else
void qsort(v,n,z,c)
register void *v;
register size_t n;
register size_t z;
register int (*c)();
#endif
{
if (n < 2) return;
if (!(__t = malloc(z))) return;
__z = z;
__c = c;
if (n > N_INSERT)
__qsort((char *)v,n);
else if (n > 1)
__isort((char *)v,n);
free(__t);
}